#include "model.h"
#include "iostream.h"

Model::Model()
{
	settings=Value(objectValue);
	execCmd=new QProcess(this);
	getSettings();
	tcEngine=new HtbEngine(&settings);
}

void Model::init()
{
	const QString makedir=(QString)getSettingsDir();
	QDir().mkdir(makedir);
	truncateFile(getSettingsDir()+"tcrules.sh");

	//Get rules from file
	tcEngine->clear();
	Value rules;
	rules=getRules();
	//Truncate rules file.
	writeJsonValueToFile(getSettingsDir()+"tcrules.json",nullValue);
	//Re-add the rules
	std::vector <std::string> ruleIndex=rules.getMemberNames();
	for(int ruleCount=0; ruleCount<ruleIndex.size(); ruleCount++)
	{
		addRule(rules[ruleIndex[ruleCount]]);
	}
	executeTcrules();
	tcEngine->debug();
}

/**
 * Retourneert de settings in JSon::Value formaat.
 */
Value* Model::getSettings()
{
	Value settings=Value(objectValue);
	settings=getJsonValueFromFile(getSettingsDir()+"settings.json");

	//If the file is empty set default values.
	if(settings.empty())
	{
		settings["device"]="eth0";
		settings["ifb"]="ifb0";
		settings["downlink"]="100000";
		settings["uplink"]="100000";
		settings["tc_cmd"]="/sbin/tc";
		settings["su_cmd"]="kdesu";
        	settings["default_bucket_rate"]="1";
        	settings["default_priority"]="3";
        	settings["default_burst"]="1500";
	}
	this->settings=settings;
	return &this->settings;
}
QString Model::getSettingsDir()
{
	return QDir::homePath()+"/.kshaper/";
}

Value Model::getRules()
{
	return getJsonValueFromFile(getSettingsDir()+"tcrules.json");
}

int Model::delRule(int ruleID)
{
	Value rules;
	
	rules=getRules();
	
	rules.removeMember(QString().setNum(ruleID).toStdString());
	
	writeJsonValueToFile(getSettingsDir()+"tcrules.json",rules);
	tcEngine->clear();
	init();
	return 0;
}

/**
 * Schrijft de settings weg in Json formaat.
 */
void Model::writeSettings(Value settings)
{
	tcEngine->clear();
	this->settings=settings;
	writeJsonValueToFile(getSettingsDir()+"settings.json",settings);
	init();
}
int Model::editRule(Value rule,int ruleID)
{
	Value rules=Value(objectValue);
	rules=getRules();

	if(rules.isMember(QString().setNum(ruleID).toStdString()))
	{
		rules.removeMember(QString().setNum(ruleID).toStdString());
		rules[QString().setNum(ruleID).toStdString()]=rule;
		writeJsonValueToFile(getSettingsDir()+"tcrules.json",rules);
		tcEngine->clear();
		init();
		return 0;
	}
	return -1;
}
int Model::addRule(Value rule)
{
	Value rules=Value(objectValue);
	rules=getRules();
	
	int classID=tcEngine->addRule(rule);
	if(classID>0)
	{
		rules[QString().setNum(classID).toStdString()]=rule;
		writeJsonValueToFile(getSettingsDir()+"tcrules.json",rules);
		return 0;	
	}
	return -1;
}


/**
 * Return system in previous state.
*/
void Model::stop()
{
	truncateFile(getSettingsDir()+"tcrules.sh");
	tcEngine->clear();
	executeTcrules();
}

QMap <QString,QString> Model::getRates()
{
	Value rules=getRules();
	QMap <QString,QString> rates;
	//rates << "";
	std::vector <std::string> ruleIndex=rules.getMemberNames();	
	for(int ruleCount=0; ruleCount<rules.size(); ruleCount++)
	{
		rates[QString().fromStdString(ruleIndex[ruleCount])]=tcEngine->getRuleStats(rules[ruleIndex[ruleCount]],QString().fromStdString(ruleIndex[ruleCount]).toInt());
	}
	return rates;
}


/**
 * Generieke functie om JSon::Value weg te schrijven naar een file in json formaat.
 */
void Model::writeJsonValueToFile(QString filename,Value jsonValue)
{
	QFile jsonFile(filename);
	FastWriter jsonWriter;

	QString jsonString=QString().fromStdString(jsonWriter.write(jsonValue));
	if(jsonFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
		QTextStream fileStream(&jsonFile);
		fileStream << jsonString;
	}
}


/**
 * Generieke functie om JSON files te lezen naar JSon::Value.
 */
Value Model::getJsonValueFromFile(QString filename)
{
	QFile jsonFile(filename);
	Reader jsonReader;
	Value jsonValue;
        QString jsonString;

       	if(jsonFile.open(QIODevice::ReadOnly)) {
		QTextStream fileStream(&jsonFile);
		do {
               		jsonString.append(fileStream.readLine());
		}
		while(!fileStream.atEnd());
	}
	jsonReader.parse(jsonString.toStdString(),jsonValue);
	return jsonValue;
}
int Model::executeTcrules()
{
	QFile::setPermissions (getSettingsDir()+"/tcrules.sh",QFile::ExeOwner | QFile::WriteOwner | QFile::ReadOwner );
	QStringList params;
	params << getSettingsDir()+"tcrules.sh";
	execCmd->start(QString().fromStdString(settings["su_cmd"].asString()),params);
	return 0;
}
int Model::truncateFile(QString filename)
{
	QFile file(filename);

	if(file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
		file.close();
		return 0;
        }
	return 1;
}
int Model::addStrToFile(QString str,QString filename)
{
	QFile file(filename);
	FastWriter writer;
	str=str+"\n";

	if(file.open(QIODevice::Append)) {
		QTextStream fileStream(&file);
		fileStream << str;
		file.close();
		return 0;
	}	
	return 1;
}
